import math
import random
import os
from pyglet import window, image, clock
from pyglet.gl import *
#from ctypes import *
#from OpenGL.GL import *
#from OpenGL.GLU import *

class GameWindow(window.Window):
    def __init__(self):
        clock.set_fps_limit(200)
        self.images = []
        window.Window.__init__(self, vsync=False)
        glClearColor(0, 0, 0, 1)
        #glColor3f(1, 0, 0)
        #glShadeModel(GL_SMOOTH)
        glClearColor(0.0, 0.0, 0.0, 0.0)
        glClearDepth(1.0)
        glEnable(GL_DEPTH_TEST)
        glDepthFunc(GL_LEQUAL)
        #glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
        #glEnable(GL_CULL_FACE)
        glEnable(GL_DEPTH_TEST)
        glAlphaFunc(GL_GREATER, 0.2)
        #glEnable(GL_ALPHA_TEST)
        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)
        #glEnable(GL_LIGHT1)
        def vec(*args):
            return (GLfloat * len(args))(*args)

        #glLightfv(GL_LIGHT0, GL_POSITION, vec(.5, .5, 1, 0))
        #glLightfv(GL_LIGHT0, GL_SPECULAR, vec(.5, .5, 1, 1))
        #glLightfv(GL_LIGHT0, GL_DIFFUSE, vec(1, 1, 1, 1))
        #glLightfv(GL_LIGHT1, GL_POSITION, vec(1, 0, .5, 0))
        #glLightfv(GL_LIGHT1, GL_DIFFUSE, vec(.5, .5, .5, 1))
        #glLightfv(GL_LIGHT1, GL_SPECULAR, vec(1, 1, 1, 1))

        #glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec(0.5, 0, 0.3, 1))
        #glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vec(1, 1, 1, 1))
        #glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 50)

    def draw_image(self, p):
        #glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        t = p.texture
        glEnable(t.target)
        glBindTexture(t.target, t.id)
        glColor3f(0.2, 0.6, 0.8)
        glEnable(GL_ALPHA_TEST)
        glBegin(GL_QUADS)
        glTexCoord2f(0.0, 0.0); glVertex3f(-.5, -0.5,  -10.)
        glTexCoord2f(1.0, 0.0); glVertex3f( .5, -.5,  -10.)
        glTexCoord2f(1.0, 1.0); glVertex3f( .5,  .5,  -10.)
        glTexCoord2f(0.0, 1.0); glVertex3f(-.5,  .5,  -10.)
        glEnd()
        glDisable(GL_ALPHA_TEST)
        #p.blit(20,30)

    def on_resize(self, width, height):
        glViewport(0, 0, width, height)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(45, 1.0*width/height, 0.1, 200.0)
        glMatrixMode(GL_MODELVIEW)
        #window.Window.on_resize(self, width, height)

    def transform(self, position, r):
        matrix = [ 1 - 2*r.v.y**2 - 2*r.v.z**2, 2*r.v.x*r.v.y - 2*r.w*r.v.z, 2*r.v.x*r.v.z + 2*r.w*r.v.y, 0,
               2*r.v.x*r.v.y + 2*r.w*r.v.z, 1 - 2*r.v.x**2 - 2*r.v.z**2, 2*r.v.y*r.v.z - 2*r.w*r.v.x, 0,
               2*r.v.x*r.v.z - 2*r.w*r.v.y, 2*r.v.y*r.v.z + 2*r.w*r.v.x, 1 - 2*r.v.x**2 - 2*r.v.y**2, 0,
               0,                           0,                           0,                           1 ]
        matrix_gl = (GLfloat * len(matrix))(*matrix)
        glLoadIdentity()
        glMultMatrixf(matrix_gl)

    def draw_list(self, call_list):
        #glClear(GL_DEPTH_BUFFER_BIT)
        glCallList(call_list)

    def draw_hud():
        #glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        t = p.texture
        glEnable(t.target)
        glBindTexture(t.target, t.id)
        glColor3f(0.2, 0.6, 0.8)
        glEnable(GL_ALPHA_TEST)
        glBegin(GL_QUADS)
        glTexCoord2f(0.0, 0.0); glVertex3f(-.5, -0.5,  -10.)
        glTexCoord2f(1.0, 0.0); glVertex3f( .5, -.5,  -10.)
        glTexCoord2f(1.0, 1.0); glVertex3f( .5,  .5,  -10.)
        glTexCoord2f(0.0, 1.0); glVertex3f(-.5,  .5,  -10.)
        glEnd()
        glDisable(GL_ALPHA_TEST)
    
def make_hud():
    glLoadIdentity()
    p = image.load("textures/crosshair.bmp")
    t = p.texture
    glEnable(t.target)
    hud = glGenLists(1)
    glNewList(hud, GL_COMPILE)
    #glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    glBindTexture(t.target, t.id)
    glEnable(GL_ALPHA_TEST)
    glBegin(GL_QUADS)
    glTexCoord2f(0.0, 0.0); glVertex3f(-.5, -0.5,  -10.)
    glTexCoord2f(1.0, 0.0); glVertex3f( .5, -.5,  -10.)
    glTexCoord2f(1.0, 1.0); glVertex3f( .5,  .5,  -10.)
    glTexCoord2f(0.0, 1.0); glVertex3f(-.5,  .5,  -10.)
    glEnd()
    glDisable(GL_ALPHA_TEST)
    glEndList()
    return hud

class StarField(object):#psyco.compact):
    def __init__(self, number, colour, depth, position, resolution):
        self.colour = colour
        self.depth = depth
        self.position = position
        self.aspect = resolution[0]/float(resolution[1])
        self.y = -self.depth*math.tan((math.pi/180)*22.5)
        coords = self.get_3dcoords()
        self.coords = [coords.next() for star in range(number)]
        self.draw_init()


    def get_3dcoords(self):
        x = self.aspect*self.y
        self.x = x
        while 1:
            yield [random.uniform(-x, x),
                random.uniform(-self.y, self.y),
                random.uniform(-self.depth, self.depth)]

    def draw(self):
        glDisable(GL_DEPTH_TEST)
        glCallList(self.stars)
        glEnable(GL_DEPTH_TEST)

    def draw_init(self):
        self.stars = glGenLists(1)
        glNewList(self.stars, GL_COMPILE)

        glBegin(GL_POINTS)
        glColor3f(*self.colour)
        for x, y, z in self.coords:
            glVertex3f(x, y, z)
        glEnd()
        glEndList()

if __name__ == "__main__":
    from sglibrary import Quaternion
    gw = GameWindow()
    s = StarField(1500, (1.0, 1.0, 1.0), -100, [0,0], (640,480))
    p = image.load("textures/crosshair.png")
    gw.transform(None,Quaternion(1, 0, 0, 0))
    while not gw.has_exit:
        gw.dispatch_events()
        gw.clear()
        gw.draw_image(p)
        s.draw()
        gw.flip()
